package com.yj.cmp.sdk.fusioncompute.compute.vm;

import com.yj.cmp.sdk.fusioncompute.common.utils.RequestUtils;
import com.yj.cmp.sdk.fusioncompute.compute.vm.dto.VmDiskExpansionDto;
import com.yj.cmp.sdk.fusioncompute.compute.vm.dto.VmMountDiskDto;
import com.yj.cmp.sdk.fusioncompute.compute.vm.dto.VmSnapshotsDto;
import com.yj.cmp.sdk.fusioncompute.compute.vm.dto.VmUnmountDiskDto;
import com.yj.cmp.sdk.fusioncompute.compute.vm.vo.VmListVo;
import com.yj.cmp.sdk.fusioncompute.compute.vm.vo.VmSnapshotsDetailVo;
import com.yj.cmp.sdk.fusioncompute.compute.vm.vo.VmSnapshotsListVo;
import com.yj.cmp.sdk.fusioncompute.compute.vm.vo.VmVo;
import com.yj.cmp.sdk.fusioncompute.identity.task.TaskVo;
import okhttp3.ResponseBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import retrofit2.Response;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author Harvey_Yang
 * @date 2021/8/28 11:14
 */
@Component
public class FcVmApi {
    private final Logger log = LoggerFactory.getLogger(FcVmApi.class);
    FcVmService fcVmService;

    public FcVmApi(FcVmService fcVmService) {
        this.fcVmService = fcVmService;
    }

    public List<VmListVo.VmsDTO> vmList(Map<String, Object> headerMap, Map<String, Object> queryParam) throws Exception {
        log.info("Query param is " + queryParam);
        List<VmListVo.VmsDTO> list = new ArrayList<>();

        Response<VmListVo> response = fcVmService.vmList(headerMap, queryParam).execute();
        RequestUtils.isSuccessful(response);
        list.addAll(response.body().getVms());
        if (response.body().getTotal() <= 100) {
            if (null != response.body()) {
                log.info("Vm list is " + list);
                return response.body().getVms();
            }
            log.info("Vm list is empty!");
            return new ArrayList<>(0);
        }

        int page = (int) Math.ceil(new Double(response.body().getTotal()) / 100);
        for (int i = 2; i <= page; i++) {
            queryParam.put("offset", i);
            queryParam.put("limit", 100);
            list.addAll(fcVmService.vmList(headerMap, queryParam).execute().body().getVms());
        }
        log.info("Vm list is " + list);
        return list;
    }

    public VmVo vmDetail(Map<String, Object> headerMap, String vmUri, Map<String, Object> queryParam) throws Exception {
        Response<VmVo> response = fcVmService.vmDetail(headerMap, vmUri, queryParam).execute();
        RequestUtils.isSuccessful(response);
        if (null == response.body()) {
            throw new RuntimeException("查询指定虚拟机为空");
        }
        return response.body();
    }

    public TaskVo creatVm(Map<String, Object> headerMap, VmVo vmVo) throws Exception {
        Response<TaskVo> response = fcVmService.creatVm(headerMap, vmVo).execute();
        RequestUtils.isSuccessful(response);
        if (null == response.body()) {
            throw new RuntimeException("任务信息为空");
        }
        return response.body();
    }

    public TaskVo deleteVm(Map<String, Object> headerMap, String vmUri, Map<String, Object> queryParam) throws Exception {
        Response<TaskVo> response = fcVmService.deleteVm(headerMap, vmUri, queryParam).execute();
        RequestUtils.isSuccessful(response);
        if (null == response.body()) {
            throw new RuntimeException("任务信息为空");
        }
        return response.body();
    }

    public TaskVo startVm(Map<String, Object> headerMap, String vmUri) throws Exception {
        Response<TaskVo> response = fcVmService.startVm(headerMap, vmUri).execute();
        RequestUtils.isSuccessful(response);
        if (null == response.body()) {
            throw new RuntimeException("任务信息为空");
        }
        return response.body();
    }

    public TaskVo stopVm(Map<String, Object> headerMap, String vmUri, Map<String, Object> queryParam) throws Exception {
        Response<TaskVo> response = fcVmService.stopVm(headerMap, vmUri, queryParam).execute();
        RequestUtils.isSuccessful(response);
        if (null == response.body()) {
            throw new RuntimeException("任务信息为空");
        }
        return response.body();
    }

    public TaskVo rebootVm(Map<String, Object> headerMap, String vmUri, Map<String, Object> queryParam) throws Exception {
        Response<TaskVo> response = fcVmService.rebootVm(headerMap, vmUri, queryParam).execute();
        RequestUtils.isSuccessful(response);
        if (null == response.body()) {
            throw new RuntimeException("任务信息为空");
        }
        return response.body();
    }

    /**
     * 查询虚拟机快照列表
     *
     * @param headerMap token
     * @param vmId      虚拟机ID
     * @return VmSnapshotsListVo(快照列表信息)
     * @throws Exception
     */
    public VmSnapshotsListVo getVmSnapshotsList(Map<String, Object> headerMap, String vmId) throws Exception {
        log.info("[vmSnapshotsList] query start, param is " + vmId);
        Response<VmSnapshotsListVo> response = fcVmService.getVmSnapshotsList(headerMap, vmId).execute();
        RequestUtils.isSuccessful(response);

        if (null == response.body()) {
            throw new RuntimeException("查询的虚拟机列表信息为空！");
        }
        log.info("VmSnapshots list is " + response.body());
        return response.body();
    }

    /**
     * 根据虚拟机ID创建快照
     *
     * @param headerMap      token
     * @param vmId           虚拟机ID
     * @param vmSnapshotsDto 创建快照的参数
     * @return TaskVo(任务信息)
     * @throws Exception
     */
    public TaskVo createVmSnapshots(Map<String, Object> headerMap, String vmId, VmSnapshotsDto vmSnapshotsDto) throws Exception {
        log.info("[createVmSnapshots] insert start, param is {}, {}", vmId, vmSnapshotsDto);
        Response<TaskVo> response = fcVmService.createVmSnapshot(headerMap, vmId, vmSnapshotsDto).execute();
        RequestUtils.isSuccessful(response);
        if (null == response.body()) {
            throw new RuntimeException("创建快照信息为空");
        }
        log.info("Return param is " + response.body());
        return response.body();
    }

    /**
     * 根据虚拟机ID查询单个快照详情
     *
     * @param headers      token
     * @param vmId         虚拟机ID
     * @param vmSnapshotId 虚拟机快照ID
     * @return VmSnapshotsDetailVo(快照详情信息)
     * @throws Exception
     */
    public VmSnapshotsDetailVo getVmSnapshotsDetail(Map<String, Object> headers, String vmId, String vmSnapshotId) throws Exception {
        log.info("[vmSnapshotsDetail] query start, param is {}, {}", vmId, vmSnapshotId);
        Response<VmSnapshotsDetailVo> response = fcVmService.getVmSnapshotsDetail(headers, vmId, vmSnapshotId).execute();
        RequestUtils.isSuccessful(response);
        if (null == response.body()) {
            throw new RuntimeException("根据ID查询指定虚拟机快照信息为空！");
        }
        log.info("Return param is " + response.body());
        return response.body();
    }

    /**
     * 根据虚拟机ID删除指定快照
     *
     * @param headerMap    token
     * @param vmId         虚拟机ID
     * @param vmSnapshotId 虚拟机快照ID
     * @return TaskVo(任务信息)
     * @throws Exception
     */
    public TaskVo deleteVmSnapshot(Map<String, Object> headerMap, String vmId, String vmSnapshotId) throws Exception {
        log.info("[deleteVmSnapshot] delete start, param is {}, {}", vmId, vmSnapshotId);
        Response<TaskVo> response = fcVmService.deleteVmSnapshot(headerMap, vmId, vmSnapshotId).execute();
        RequestUtils.isSuccessful(response);
        if (null == response.body()) {
            throw new RuntimeException("删除虚拟机返回的任务信息为空！");
        }
        log.info("Return param is " + response.body());
        return response.body();
    }

    /**
     * 根据指定虚拟机快照恢复虚拟机
     *
     * @param headerMap    token
     * @param vmId         虚拟机ID
     * @param vmSnapshotId 虚拟机快照ID
     * @return TaskVo(任务信息)
     * @throws Exception
     */
    public TaskVo restoreVmBySnapshot(Map<String, Object> headerMap, String vmId, String vmSnapshotId) throws Exception {
        log.info("[restoreVmBySnapshot] restore start, param is {}, {}", vmId, vmSnapshotId);
        Response<TaskVo> response = fcVmService.restoreVmBySnapshot(headerMap, vmId, vmSnapshotId).execute();
        RequestUtils.isSuccessful(response);
        if (null == response.body()) {
            throw new RuntimeException("虚拟机快照恢复虚拟机返回的任务信息为空！");
        }
        log.info("Return param is " + response.body());
        return response.body();
    }

    /**
     * 修改指定虚拟机快照信息
     *
     * @param headerMap      token
     * @param vmId           虚拟机ID
     * @param vmSnapshotId   虚拟机快照ID
     * @param vmSnapshotsDto 修改快照的信息
     * @return Integer(用于接收响应状态码)
     * @throws Exception
     */
    public Integer updateVmSnapshot(Map<String, Object> headerMap, String vmId, String vmSnapshotId, VmSnapshotsDto vmSnapshotsDto) throws Exception {
        log.info("[updateVmSnapshot] update start, param is {}, {}, {}", vmId, vmSnapshotId, vmSnapshotsDto);
        Response<ResponseBody> response = fcVmService.updateVmSnapshot(headerMap, vmId, vmSnapshotId, vmSnapshotsDto).execute();
        RequestUtils.isSuccessful(response);
        log.info("Return status code is " + response.code());
        return response.code();
    }

    /**
     * 查询指定虚拟机的vss状态
     *
     * @param headerMap token
     * @param vmId      虚拟机ID
     * @return Map(接收vss状态)
     * @throws Exception
     */
    public Map<String, Object> getVmVssStatus(Map<String, Object> headerMap, String vmId) throws Exception {
        log.info("[vmVssStatus] query start, param is " + vmId);
        Response<Map<String, Object>> response = fcVmService.getVmVssStatus(headerMap, vmId).execute();
        RequestUtils.isSuccessful(response);
        if (null == response.body()) {
            throw new RuntimeException("查询指定虚拟机的vss状态返回信息为空！");
        }
        log.info("Return result is " + response.body());
        return response.body();
    }

    /**
     * 根据指定虚拟机ID挂载磁盘
     *
     * @param headerMap      token
     * @param vmId           虚拟机ID
     * @param vmMountDiskDto 虚拟机挂载磁盘参数
     * @return TaskVo(任务信息)
     * @throws Exception
     */
    public TaskVo mountVmDisk(Map<String, Object> headerMap, String vmId, VmMountDiskDto vmMountDiskDto) throws Exception {
        log.info("[vmMountDisk] mount start, param is {}, {}", vmId, vmMountDiskDto);
        Response<TaskVo> response = fcVmService.mountVmDisk(headerMap, vmId, vmMountDiskDto).execute();
        RequestUtils.isSuccessful(response);
        if (null == response.body()) {
            throw new RuntimeException("虚拟机磁盘挂载返回的任务信息为空!");
        }
        log.info("Return result is " + response.body());
        return response.body();
    }

    /**
     * 根据指定虚拟机ID卸载磁盘
     *
     * @param headerMap        token
     * @param vmId             虚拟机ID
     * @param vmUnmountDiskDto 虚拟机卸载磁盘参数
     * @return TaskVo(任务信息)
     * @throws Exception
     */
    public TaskVo unmountVmDisk(Map<String, Object> headerMap, String vmId, VmUnmountDiskDto vmUnmountDiskDto) throws Exception {
        log.info("[vmUnmountDisk] unmount start, param is {}, {}", vmId, vmUnmountDiskDto);
        Response<TaskVo> response = fcVmService.unmountVmDisk(headerMap, vmId, vmUnmountDiskDto).execute();
        RequestUtils.isSuccessful(response);
        if (null == response.body()) {
            throw new RuntimeException("虚拟机磁盘卸载返回的任务信息为空!");
        }
        log.info("Return result is " + response.body());
        return response.body();
    }

    /**
     * 根据指定虚拟机ID扩容磁盘
     *
     * @param headerMap          token
     * @param vmId               虚拟机ID
     * @param vmDiskExpansionDto 虚拟机扩容参数
     * @return TaskVo(任务信息)
     * @throws Exception
     */
    public TaskVo expandVmDisk(Map<String, Object> headerMap, String vmId, VmDiskExpansionDto vmDiskExpansionDto) throws Exception {
        log.info("[vmDiskExpansion] expand start, param is {}, {}", vmId, vmDiskExpansionDto);
        Response<TaskVo> response = fcVmService.expandVmDisk(headerMap, vmId, vmDiskExpansionDto).execute();
        RequestUtils.isSuccessful(response);
        if (null == response.body()) {
            throw new RuntimeException("虚拟机磁盘扩容返回的任务信息为空!");
        }
        log.info("Return result is " + response.body());
        return response.body();
    }

}
